import React ,{Component} from 'react'
import {
  Card,
  Icon,
  Form,
  Input,
  Cascader,
  Button,
  message
} from 'antd'

import LinkButton from '../../components/link-button'
import {reqCategorys,reqAddOrUpdateProduct} from '../../api'
import PicturesWall from './pictures-wall'
import RichTextEditor from './rich-text-editor'
// import memoryUtils from '../../utils/memoryUtils'  hash

const {Item} = Form
const { TextArea } = Input


class ProductAddUpdate extends Component{

 
  state={
     options:[],   // 
  }

  constructor(props){
     super(props)
     // 创建用来保存ref标识的标签对象的容器
     this.pw = React.createRef()
     this.editor = React.createRef()
  }

  initOptions =async (categorys)=>{
    // 根据categorys数组 生成options数组
    const options = categorys.map((c,key)=>({
      value:c._id,
      label:c.name,
      isLeaf:false,  // false 不是叶子 有下级数据了  是叶子 没有下级数据
    }))

    // 如果是一个二级分类商品的更新
    const {isUpdate, product} = this
    const {pCategoryId} = product
    if(isUpdate && pCategoryId !=='0'){
       // 获取对应的二级分类列表
       const subCategorys = await this.getCategorys(pCategoryId)
       // 生成二级下拉列表的options
       const childOptions = subCategorys.map(c=>({
          value:c._id,
          label:c.name,
          isLeaf:true,  // 不是叶子 有下级数据了  是叶子 没有下级数据
        }))
        // 找到当前商品对应的一级option对象
        const targetOption = options.find(option=>option.value ===pCategoryId )
        // 关联对应的一级option上
        targetOption.children = childOptions

    }


    // 更新options状态
    this.setState({
       options
    })
  }

  // 用加载下一级列表的回调函数
  loadData =async (selectedOptions)=>{
     console.log('0000',selectedOptions);
     // 得到选择的option对象
     const targetOption = selectedOptions[0]
     // 显示loading
     targetOption.loading = true

     // 根据选中的分类, 请求获取二级分类列表
     const subCategorys =await this.getCategorys(targetOption.value)
     // 隐藏loading
     targetOption.loading = false
     // 二级分类数组有数据
     if(subCategorys && subCategorys.length>0){
       // 生成一个二级列表的options
       const childOptions = subCategorys.map(c=>({
          value:c._id,
          label:c.name,
          isLeaf:true,  // 不是叶子 有下级数据了  是叶子 没有下级数据
        }))
        // 关联到当前option上
        targetOption.children = childOptions
     }else{ // 当前选中的分类没有二级分类
        targetOption.isLeaf = true;
     }
     
     // 更新options状态   拷贝出一个新的数组/对象  内容一样  使用 pureComponent 必须这样写  [...this.state.options]
      this.setState({
        options: [...this.state.options],
      })
  }

    /*
     异步获取一级/二级分类列表, 并显示
      async函数的返回值是一个新的promise对象, promise的结果和值由async的结果来决定
   */
  getCategorys = async (parentId) => {
    const result = await reqCategorys(parentId)   // {status: 0, data: categorys}
    if (result.status===0) {
      const categorys = result.data
      // 如果是一级分类列表
      if (parentId==='0') {
        this.initOptions(categorys)
      } else { // 二级列表
        return categorys  // 返回二级列表 ==> 当前async函数返回的promsie就会成功且value为categorys
      }
    }
  }

  componentDidMount () {
     this.getCategorys('0')
  }

  // hash  再卸载之前 清除保存的数据
  // componentWillUnmount(){
  //   memoryUtils.product = {}
  // }

  // 在 render 之前执行
  componentWillMount () {
     // 取出携带的state
     const product = this.props.location.state  // 如果是新增没值, 否则有值
     // hash  const product =  memoryUtils.product
     // 保存是否是修改的标识  强制转换boolean
     //  hash this.isUpdate = !!product._id
     this.isUpdate = !!product
     // 保存商品(如果没有, 保存是{})
     this.product = product || {}
  }

    submit =()=>{
       // 进行表单验证, 如果通过了, 才发送请求
    this.props.form.validateFields(async (error, values) => {
      if (!error) {
           // 1. 收集数据, 并封装成product对象
           const { name,desc,price,categoryIds} = values
           let pCategoryId,categoryId;
           // 一级分类
           if(categoryIds.length===1){
              pCategoryId ='0';
              categoryId = categoryIds[0]
           }else{ // 收集的二级分类
              pCategoryId =categoryIds[0]
              categoryId = categoryIds[1]
           }
           const imgs = this.pw.current.getImgs();
           console.log('66666',imgs);
           const detail = this.editor.current.getDetail();
           console.log('77777',detail);
           const product = { name,desc,price,imgs,detail,pCategoryId,categoryId }
           console.log('product---000--aaa',product);
           
           // 如果是更新, 需要添加_id
           if(this.isUpdate){
              product._id = this.product._id
           }
           // 2. 调用接口请求函数去添加/更新
           const res = await reqAddOrUpdateProduct(product);
           // 3. 根据结果提示
           if(res.status ===0){
             message.success(`${this.isUpdate ? '更新' : '添加'}商品成功!`)
             this.props.history.goBack()
           }else {
             message.error(`${this.isUpdate ? '更新' : '添加'}商品失败!`)
            }
         }
    })
  }
    /*
     验证价格的自定义验证函数
   */
  validatePrice = (rule, value, callback) => {
      //console.log(value, typeof value)
      if (value*1 > 0) {
        callback() // 验证通过
      } else {
        callback('价格必须大于0') // 验证没通过
      }
   }

     render(){
       const { isUpdate,product} = this
       const {pCategoryId, categoryId,imgs,detail} = product
       // 用来接收级联分类ID的数组
       const categoryIds = []
       // 修改
       if(isUpdate){
          // 商品是一个一级分类的商品
          if(pCategoryId==='0'){
            categoryIds.push(pCategoryId)
          }else{// 商品是一个二级分类的商品
            categoryIds.push(pCategoryId)
            categoryIds.push(categoryId)
          }
       }
      // 头部左侧标题
      const title = (
        <span>
          <LinkButton onClick={() => this.props.history.goBack()}>
            <Icon type='arrow-left' style={{fontSize: 20}}/>
          </LinkButton>
          <span> { isUpdate ? '修改商品' : '添加商品' }</span>
        </span>
      )

      // 指定Item布局的配置对象
      const formItemLayout = {
        labelCol: { span: 2 },  // 左侧label的宽度
        wrapperCol: { span: 8 }, // 右侧包裹的宽度
      }

      const {getFieldDecorator} = this.props.form

      return (
        <Card title={title}>
        <Form {...formItemLayout}>
          <Item label="商品名称">
            {
              getFieldDecorator('name', {
                initialValue: product.name,
                rules: [
                  {required: true, message: '必须输入商品名称'}
                ]
              })(<Input placeholder='请输入商品名称'/>)
            }
          </Item>
          <Item label="商品描述">
            {
              getFieldDecorator('desc', {
                initialValue: product.desc,
                rules: [
                  {required: true, message: '必须输入商品描述'}
                ]
              })(<TextArea placeholder="请输入商品描述" autoSize ={{ minRows: 2, maxRows: 6 }} />)
            }

          </Item>
          <Item label="商品价格">
            {
              getFieldDecorator('price', {
                initialValue: product.price,
                rules: [
                  {required: true, message: '必须输入商品价格'},
                  {validator: this.validatePrice}
                ]
              })(<Input type='number' placeholder='请输入商品价格' addonAfter='元'/>)
            }
          </Item>
          <Item label="商品分类">
          
            {
              getFieldDecorator('categoryIds', {
                initialValue: categoryIds,
                rules: [
                  {required: true, message: '必须指定商品分类'},
                ]
              })(
                <Cascader
                  placeholder='请指定商品分类'
                  options={this.state.options}  /*需要显示的列表数据数组*/
                  loadData={this.loadData} /*当选择某个列表项, 加载下一级列表的监听回调*/
                />
              )
            }
          </Item>
          <Item label="商品图片">
             <PicturesWall ref={this.pw} imgs={imgs} />
           </Item>
           <Item label="商品详情" labelCol={{span: 2}} wrapperCol={{span: 20}}>
             <RichTextEditor ref={this.editor} detail={detail}/>
           </Item>
          <Item>
            <Button type='primary' onClick={this.submit}>提交</Button>
          </Item>
        </Form>
      </Card>
      )
    }
}


export default Form.create()(ProductAddUpdate)



/*
1. 子组件调用父组件的方法: 将父组件的方法打包给 一个属性 传递给 子组件, 子组件调用属性就是调用父组件方法
2. 父组件调用子组件的方法: 在父组件中通过ref得到子组件标签对象(也就是组件对象), 调用其方法
 */

/*
使用ref
1. 创建ref容器: thi.pw = React.createRef()
2. 将ref容器交给需要获取的标签元素: <PictureWall ref={this.pw} />
3. 通过ref容器读取标签元素: this.pw.current
4  最好通过方法 this.pw.current.方法 获取 state里面的值 
 */